package com.karrim.server.util;

import com.google.common.hash.HashCode;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import com.google.inject.Inject;
import com.karrim.server.util.array.LinkedDynamicArray;
import com.karrim.server.util.def.HasSize;
import com.karrim.server.util.def.Splittable;
import java.util.Arrays;

/**
 *
 * @author andrea.cantafio
 */
public class StringImpl implements CharSequence, HasSize<Integer>, Splittable<Character> {

    @Inject
    public StringImpl() {
        size = 0;
    }

    public StringImpl(char[] cs) {
        this.cs = cs;
        size = cs.length;
    }

    public StringImpl(String s) {
        this(s.toCharArray());
    }

    public StringImpl append(CharSequence charSequence) {
        int currentLength = cs.length, newLength = charSequence.length();
        char[] result = new char[currentLength + newLength];
        System.arraycopy(cs, 0, result, 0, currentLength);
        for (int i = 0; i < newLength; i++) {
            result[i + currentLength] = charSequence.charAt(i);
        }
        size = result.length;
        return new StringImpl(result);
    }

    @Override
    public char charAt(int index) {
        return cs[index];
    }

    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof StringImpl) {
            StringImpl s = (StringImpl) obj;
            return Arrays.equals(cs, s.cs);
        }
        return false;
    }

    @Override
    public Integer getCapacity() {
        return cs.length;
    }

    @Override
    public Integer getSize() {
        return size;
    }

    @Override
    public int hashCode() {
        HashFunction hashFunction = Hashing.md5();
        HashCode hashCode = hashFunction.newHasher().putString(this).hash();
        return hashCode.asInt();
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public int length() {
        return cs.length;
    }

    public StringImpl[] split(char splitter) {
        LinkedDynamicArray<StringImpl> arr = new LinkedDynamicArray<StringImpl>();
        int last = 0;
        for (int i = 0; i < size; i++) {
            if (cs[i] == splitter) {
                arr.add((StringImpl) subSequence(last, i));
                last = i + 1;
            }
        }
        StringImpl s = (StringImpl) subSequence(last, cs.length);
        if (!"".equals(s)) {
            arr.add((StringImpl) subSequence(last, cs.length));
        }
        return arr.toArray();
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        return new StringImpl(Arrays.copyOfRange(cs, start, end));
    }

    @Override
    public Character[] toArray() {
        Character[] result = new Character[cs.length];
        for (int i = 0; i < cs.length; i++) {
            result[i] = cs[i];
        }
        return result;
    }

    @Override
    public String toString() {
        return new String(cs);
    }
    private char[] cs = {};
    private int size;
}
